package serveurs;
/**
 *  GedServeur
 *
 *
 * @author Peloux Arnaud</a>
 * @version 1.0
 */


import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.StringReader;
import java.util.Vector; //thread Safe
import org.apache.commons.codec.binary.Base64;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;

import Outils.SimpleContentHandler;


public class GedServeur extends Thread{
	/**
	 * Attributs 
	 */
	private Vector <GedClasses> mesClasses;
	private Vector <Utilisateurs> mesUtilisateurs;
	private String RACINE;
	private final String FICHIER_SAUVEGARDE="Gedsauve.xml";
	int BUFFER_SIZE = 4096;
	 
	 
	/**
	 * Constructeurs
	 */
	public GedServeur(String racine){
		this.RACINE = racine;
		mesClasses = new Vector<GedClasses>();
		mesUtilisateurs = new Vector<Utilisateurs>();
		
		
		if (!existenceFichier(racine+FICHIER_SAUVEGARDE)){ 
			//initialisation des classes et utilisateurs
			mesClasses.add(new GedClasses("Defaut","C1","U1", null));
			mesUtilisateurs.add(new Utilisateurs("Administrateur","U1"));}
		else if(!importFromFichier(racine+FICHIER_SAUVEGARDE))
			System.out.println("Erreur, fichier XML incorrect.");
		Exec.logger.fatal("Erreur, fichier XML incorrect.");
		return;
	 }
	public GedServeur(String racine, String systeme){
		this.RACINE = racine;
		importFromFichier(racine+FICHIER_SAUVEGARDE);
		
		mesClasses = new Vector<GedClasses>();
		mesUtilisateurs = new Vector<Utilisateurs>();
		//initialisation des classes et utilisateurs
		mesClasses.add(new GedClasses("Defaut","C1","U1", null));
		mesUtilisateurs.add(new Utilisateurs("Administrateur","U1"));
	 }
	
	/**
	 * Acesseurs
	 */
	public GedClasses getGedClasse(String uid){
		for (int i=0; i<mesClasses.size();i++){
			if(uid.equalsIgnoreCase(mesClasses.get(i).getUid())){
				return mesClasses.get(i);
			}
		}	
		return null;
	}
	public GedClasses getGedClassefromName(String name){
		for (int i=0; i<mesClasses.size();i++){
			if(name.equalsIgnoreCase(mesClasses.get(i).getName())){
				return mesClasses.get(i);
			}
		}	
		return null;
	}
	public Utilisateurs getUtilisateurs(String uid){
		for (int i=0; i<mesUtilisateurs.size();i++){
			if(uid.equalsIgnoreCase(mesUtilisateurs.get(i).getUid())){
				return mesUtilisateurs.get(i);
			}
		}	
		return null;
	}
	public Utilisateurs getUtilisateurs(int index){
	
			if(index<mesUtilisateurs.size()){
				return mesUtilisateurs.get(index);
			}
			
		return null;
	}
	public String getFICHIER_SAUVEGARDE(){
		return FICHIER_SAUVEGARDE;
	}
	public String getRacine(){
		return RACINE;
	}
	
	/**
	 * Méthodes
	 */
	
		/*
		 * 	  Gestion des de la sauvegarde/import 
		 */
	 
	private boolean existenceFichier(String url){
		if (url==null) return false;
		try {
			 //test de l'existence du fichier
			FileReader fileReader = new FileReader(url);
			fileReader.close();
		} catch (Exception e) {
			
			return false;
		}
		return true;
	}
 	private synchronized boolean importFromFichier(String url){
 		// retourne true si fichier bien importé
		 if (url==null) return false;
		 		
			try {
			XMLReader saxReader = XMLReaderFactory.createXMLReader();
            SimpleContentHandler test =new SimpleContentHandler(this);
            saxReader.setContentHandler(test);
            saxReader.parse(url);
			} catch (Exception e) {
				Exec.logger.fatal("erreur de parsage", e);
				return false;
			}
		return true;
	}

	
	public synchronized boolean saveToFichier(){
		// retourne true si fichier bien sauvegardé
		// création du fichier xml
		FileWriter fr;
		try {
			fr = new FileWriter(RACINE+FICHIER_SAUVEGARDE);
			fr.write(createXml());
			fr.close();
		} catch (IOException e) {

			System.out.println( "la sauvegarde a échouée");
			Exec.logger.fatal("la sauvegarde a échouée");
			return false;
		}
		
		return true;
	}
	
	private synchronized String createXml(){
		StringBuffer sb = new StringBuffer();
		sb.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n");
		sb.append("<Ged>\n");
		 // export des utilisateurs
			for(int i=0; i<getNbUtilisateurs();i++)
				sb.append("<NewGedUtilisateurs uid=\""+mesUtilisateurs.get(i).getUid()+"\" nom=\""+mesUtilisateurs.get(i).getName()+"\"/>\n");
		 // export des Classes
			for(int i=0; i<getNbGedClasses();i++){
				sb.append("<NewGedClasses uid=\""+mesClasses.get(i).getUid()+"\" nom=\""+mesClasses.get(i).getName()+"\" uidProprietaire=\""+mesClasses.get(i).getUidProprietaire()+"\"/>\n");
		 // export des types/nom des Attributs pour les classes		
				for(int j=0; j< mesClasses.get(i).getNbAttributs();j++)
						sb.append("<NomAttributs type=\""+mesClasses.get(i).getTypeAttributs(j)+"\" nom=\""+mesClasses.get(i).getNomAttributs(j)+"\" uidGedClasses=\""+mesClasses.get(i).getUid()+"\"/>\n");	
			}
			for (int i=0;i<getNbGedClasses();i++)
				for (int j=0;j<mesClasses.get(i).getnbDocs();j++){
		 // export des Documents pour les classes			
					sb.append("<GedDocuments uid=\""+mesClasses.get(i).getGedDocs(j).getUid()+"\" nom=\""+mesClasses.get(i).getGedDocs(j).getNom()+"\" uidProprietaire=\""+mesClasses.get(i).getGedDocs(j).getUidPropietaire()+"\" uidGedClasses=\""+mesClasses.get(i).getUid()+"\"/>\n");
					sb.append("<GedDataDocuments uid=\""+mesClasses.get(i).getGedDocs(j).getUid()+"\" nom=\""+mesClasses.get(i).getGedDocs(j).getNom()+"\" donnees=\""+base64EncodeFile(RACINE+mesClasses.get(i).getGedDocs(j).getNom())+"\"/>\n");
					for(int k=0;k<mesClasses.get(i).getNbAttributs();k++)
		// export des Attributs des documents				
						sb.append("<DocsAttribut uid=\""+mesClasses.get(i).getGedDocs(j).getAttribut(k).getUid()+"\" valeur=\""+mesClasses.get(i).getGedDocs(j).getAttribut(k).getAttribut()+"\" uidGedDocuments=\""+mesClasses.get(i).getGedDocs(j).getUid()+"\" uidGedClasses=\""+mesClasses.get(i).getUid()+"\"/>\n");
				}
					
		
			
		
		sb.append("</Ged>");
		return sb.toString();
	}


	
			/*
			 * Gestion des Utilisateurs 
			 */
	public boolean createUtilisateur(String name){
		// retourne true si user créé 
		if(!rechercheUtilisateur(name))return false;
		String temp;
		
		int i=1,val=mesUtilisateurs.size()+i;;
		temp ="U"+val;
		
		while(! rechercheNameUtilisateur(temp).equalsIgnoreCase("0")){
			i++;
			val=mesUtilisateurs.size()+i;
			temp ="U"+val;
			System.out.println(temp);
			if(i<=5000)return false;
		}
		mesUtilisateurs.add(new Utilisateurs(name,temp));
		createGedClasses("Classe defaut "+name, temp, null);
		return true;
	}
	public boolean createUtilisateur(String name, String uid){
		if(!rechercheUtilisateur(name) | !rechercheNameUtilisateur(uid).equalsIgnoreCase("0"))return false;
		mesUtilisateurs.add(new Utilisateurs(name,uid));
		return true;
	}
	public boolean deleteUtilisateur(String name){
		// return false si pas fait
		String newUid= "U1";
		int temp =rechercheIndexUtilisateur(name);
		String uidUtilisateur = mesUtilisateurs.get(temp).getUid();
		String[] uidGedClassesTemp= rechercheListUidGedClassesByUidProprietaire(uidUtilisateur);
		if(rechercheUtilisateur(name)| temp ==0)return false;
		for(int i=0;i<uidGedClassesTemp.length;i++){
			GedClasses GedClasseTemp = getGedClasse(uidGedClassesTemp[i]);
			GedClasseTemp.setUidProprietaire(newUid);
			for (int j=0; j<GedClasseTemp.getnbDocs();j++){
				GedClasseTemp.getGedDocs(j).setUidProprietaire(newUid);
				
			}
			
		}
		mesUtilisateurs.remove(temp);
		saveToFichier();
		return true;
	}
	public boolean modifyNameUtilisateur(String name, String newName){
		//retourne true si nom changé
		if (rechercheUtilisateur(name))return false;
		mesUtilisateurs.get(rechercheIndexUtilisateur(name)).setName(newName);
		return true;
	}
	public boolean rechercheUtilisateur(String nomUtilisateur){
		//Retourne TRUE si l'utilisateur n'existe pas
	
		for(int i=1; i<mesUtilisateurs.size();i++){
			if(mesUtilisateurs.get(i).getName().equalsIgnoreCase(nomUtilisateur))
				return false;
		}
		return true;
	}
	public int rechercheIndexUtilisateur(String nomUtilisateur){
		//Retourne TRUE si l'utilisateur n'existe pas
		if (mesUtilisateurs.size()==1 && nomUtilisateur.equalsIgnoreCase("Administrateur")) return 0;
		for(int i=1; i<mesUtilisateurs.size();i++){
			if(mesUtilisateurs.get(i).getName().equalsIgnoreCase(nomUtilisateur))
				return i;
		}
		return 0;
	}
	public String rechercheUidUtilisateur(String nomUtilisateur){
		//Retourne TRUE si l'utilisateur n'existe pas
		if (nomUtilisateur.equalsIgnoreCase("Administrateur")) return "U1";
		for(int i=0; i<mesUtilisateurs.size();i++){
			if(mesUtilisateurs.get(i).getName().equalsIgnoreCase(nomUtilisateur))
				return mesUtilisateurs.get(i).getUid();
		}
		return "0";
	}	
	public String rechercheNameUtilisateur(String uid){
		//Retourne "0" si l'utilisateur n'existe pas
		if (mesUtilisateurs.size()==1 && uid.equalsIgnoreCase("U1")) return "0";
		for(int i=1; i<mesUtilisateurs.size();i++){
			if(mesUtilisateurs.get(i).getUid().equalsIgnoreCase(uid))
				return mesUtilisateurs.get(i).getName();
		}
		return "0";
	}		
	public int getNbUtilisateurs(){
		return mesUtilisateurs.size();
	}
	public String listUtilisateur(){
		StringBuffer sb = new StringBuffer();
		for (int i=0; i<mesUtilisateurs.size();i++)
			sb.append(mesUtilisateurs.get(i).getName()+"\n");
		
		return sb.toString();
	}
			/*
			 * Gestion des Classes 
			 */
	public boolean createGedClasses(String name, String uidproprietaire, String[] attributs){
		if(!rechercheGedClasses(name))return false;
		String temp;
		int i=1;
		temp ="C"+i;
		
		while(! rechercheNameGedClasses(temp).equalsIgnoreCase("0")){
			i++;
			
			temp ="C"+i;
			if(i>=5000)return false;
		}
		mesClasses.add(new GedClasses(name,temp,uidproprietaire,attributs));
		
		return true;
	}
	public boolean createGedClasses(String name,String uid, String uidproprietaire, String[] attributs){

		if(!rechercheGedClasses(name)| !rechercheUidUtilisateur(uidproprietaire).equalsIgnoreCase("0")|!rechercheNameGedClasses(uid).equalsIgnoreCase("0"))return false;
		mesClasses.add(new GedClasses(name,uid,uidproprietaire,attributs));
		return true;
	}
	public boolean deleteGedClasse(String name){
		// return false si pas fait
		int temp =rechercheIndexGedClasses(name);
		if(rechercheGedClasses(name)| temp ==0)return false;
		mesClasses.remove(temp);
		return true;
	}
	public boolean modifyNameGedClasses(String name, String newName){
		//retourne true si nom changé
		if (rechercheGedClasses(name))return false;
		mesClasses.get(rechercheIndexGedClasses(name)).setName(newName);
		return true;
	}
	public boolean modifyProprietaireGedClasses(String name, String newUidProprietaire){
		//retourne true si proprietaire changé
		if (rechercheGedClasses(name))return false;
		mesClasses.get(rechercheIndexGedClasses(name)).setUidProprietaire(newUidProprietaire);
		return true;
	}
	public boolean rechercheGedClasses(String name){
		//retourne TRUE si la classe n'existe pas
		if (mesClasses.size()==1 && name.equalsIgnoreCase("defaut")) return true;
		for(int i=1; i<mesClasses.size();i++){
			if(mesClasses.get(i).getName().equalsIgnoreCase(name))
				return false;
		}
		return true;
	}
	public int rechercheIndexGedClasses(String nomClasses){
		//Retourne TRUE si la GedClasses n'existe pas
		if (mesClasses.size()==1 && nomClasses.equalsIgnoreCase("Defaut")) return 0;
		for(int i=1; i<mesClasses.size();i++){
			if(mesClasses.get(i).getName().equalsIgnoreCase(nomClasses))
				return i;
		}
		return 0;
	}
	public String rechercheUidGedClasses(String nomGedClasses){
		//Retourne null si la GedClasses n'existe pas
		if (mesClasses.size()==1 && nomGedClasses.equalsIgnoreCase("Defaut")) return null;
		for(int i=1; i<mesClasses.size();i++){
			
			if(mesClasses.get(i).getName().equalsIgnoreCase(nomGedClasses))
				return mesClasses.get(i).getUid();
		}
		return null;
	}	
	public String[] rechercheListUidGedClassesByUidProprietaire(String uidproprietaire){
		String[] retour, temp = new String[mesClasses.size()];
		int j=0;
		for (int i=0;i<mesClasses.size();i++){
			if (mesClasses.get(i).getUidProprietaire().equalsIgnoreCase(uidproprietaire)|uidproprietaire.equalsIgnoreCase("U1") ){
			temp[j]=mesClasses.get(i).getUid();
			j++;
			}
		}
		retour= new String[j];
		for(int i=0;i<j;i++)
			retour[i]=temp[i];
		return retour;
	}
	public String rechercheNameGedClasses(String uid){
		//Retourne "0" si la GedClasses n'existe pas

		for(int i=0; i<mesClasses.size();i++){
			if(mesClasses.get(i).getUid().equalsIgnoreCase(uid))
				return mesClasses.get(i).getName();
		}
		return "0";
	}
	public int getNbGedClasses(){
		return mesClasses.size();
	}
	public String[] rechercheListGedDocumentsByUidProporietaire(String uidProprietaire){
		Vector<String> temp = new Vector<String>();
		String[] retour, tmp = rechercheListUidGedClassesByUidProprietaire(uidProprietaire);
			for (int i=0;i<tmp.length;i++){
				GedClasses gedClasseTemp =getGedClasse(tmp[i]);
				
				for(int j=0;j<gedClasseTemp.getnbDocs();j++){
					temp.addElement(gedClasseTemp.getGedDocs(j).getNom());
				}	
			}
		
		retour = new String[temp.size()];
		for (int i=0;i<temp.size();i++)
			retour[i]= temp.get(i);
		return retour;
		
	}
		/*
		 * Gestion du Base64
		 */
	protected String base64EncodeFile(String url){
		StringBuffer sb = new StringBuffer();
		byte[]  temp;
		try {
		
		BufferedInputStream input = new BufferedInputStream(new FileInputStream(url));
			
			  byte[] buf = new byte[3000000];
	
			  while (true) {
			   int len = input.read(buf);
			   if (len == -1){
				   input.close();
				   return sb.toString();}
			   temp= new byte[len];
			   for(int i=0;i<len;i++)
				   temp[i]= buf[i];
			   sb.append(Base64.encodeBase64String(temp));
			  
			  }
		
		
		} catch (Exception e) {
			System.out.println(" Erreur: le Fichier "+url+" n'a pu être sauvegardé. ");
			Exec.logger.fatal(" Erreur: le Fichier "+url+" n'a pu être sauvegardé. ", e);
			return null;
		}
	}
	public synchronized boolean  base64DecodetoFile(String nomFichier, String chaineB64){
		if (nomFichier==null |chaineB64==null )return false;
		int i=0;
		byte[]temp;
		try{
		OutputStream output = new FileOutputStream(RACINE+nomFichier);
		temp =Base64.decodeBase64(chaineB64);
		for(;i<temp.length;i++){
		    output.write(temp[(int) i]);
		}	
		output.close();
		return true;}
		
		catch(Exception e){
			System.out.println(" Erreur: le Fichier "+nomFichier+" n'a pu être restauré. ");
			Exec.logger.fatal(" Erreur: le Fichier "+nomFichier+" n'a pu être restauré. ", e);
			return false;
		}
		
	}
		
		/*
		 * gestion des commandes
		 */
	synchronized boolean  stringXmlCommande(String xmlCommande){
		if (xmlCommande ==null) return false;
		try {
			XMLReader saxReader = XMLReaderFactory.createXMLReader();
            SimpleContentHandler test =new SimpleContentHandler(this);
            saxReader.setContentHandler(test);
            saxReader.parse(new InputSource(new StringReader(xmlCommande)));
			} catch (Exception e) {
				Exec.logger.fatal("erreur de parsage xml",e);
				return false;
			}
		return true;
		
	} 
	
	
}
